In [1]:
import pandas as pd
import panel as pn
import holoviews as hv
import hvplot.pandas
from bokeh.models.formatters import NumeralTickFormatter
formatter = NumeralTickFormatter(format="0,0")
from numpy import arange
hv.extension('bokeh')
In [2]:
from SupportFile import mkt_inputs, vol_sensitivity, value_shocks
mkt_inputs
Out[2]:
fwd rate black vol
exp x tenor
2x2 3.17 44.08
2x5 2.98 40.20
2x10 2.96 35.40
5x2 2.92 37.96
5x5 2.95 34.42
5x10 2.93 31.29
In [3]:
pn.Tabs(*[hv.Bars(vol_sensitivity[i].rename('PV01'), name = i).opts(width = 800) for i in vol_sensitivity.columns])
Out[3]:
In [4]:
def adjust_shocks_for_cev(
        value_shocks:pd.Series
        , vol_sensitivity:pd.DataFrame
        , base_vol:pd.Series
        , fwd_rates:pd.Series
        , cev_vol:float):
    combined_index = pd.MultiIndex.from_product([value_shocks.index, mkt_inputs.index])
    shocked_vol = combined_index.to_frame().join(mkt_inputs)
    shocked_vol['cev vol'] = shocked_vol['black vol'] * ((shocked_vol['fwd rate'])**(1 - cev_vol))
    shocked_vol['new black vol'] = (
        shocked_vol['cev vol'] * ((shocked_vol['fwd rate'] + shocked_vol['ShockAmt'] * 0.01)**(cev_vol - 1))
    )
    shocked_vol['black vol chg'] = shocked_vol['new black vol'] - shocked_vol['black vol']
    cev_adjusted_vol_shocks = shocked_vol['black vol chg'].unstack('exp x tenor')[vol_sensitivity.columns]
    cev_val_adj = cev_adjusted_vol_shocks * vol_sensitivity
    cev_adjusted_val_shocks = cev_val_adj.sum(axis = 1) + value_shocks
    cev_adjusted_val_shocks.name = 'const cev shocks'
    both_shocks = value_shocks.to_frame(name = 'const black shocks').join(cev_adjusted_val_shocks)
    return both_shocks
    
In [5]:
def grapher(cev = 0.5):
    out = adjust_shocks_for_cev(
        value_shocks
        , vol_sensitivity
        , mkt_inputs['black vol']
        , mkt_inputs['fwd rate']
        , cev)   
    return out.hvplot()

hdict = {i:grapher(i) for i in arange(0.0,1.05,.05)}
In [6]:
hv.output(widget_location='top_left')
x = hv.HoloMap(hdict, kdims = ['cev'])
x.kdims[0].default = 0.5
x.opts(yformatter = formatter)
Out[6]: